package com.eastfair.home.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.home.dao.BuilderRepairReportMapper;
import com.eastfair.home.dto.BuilderRepairReportDTO;
import com.eastfair.home.entity.BuilderRepairReport;
import com.eastfair.home.enumeration.BuilderRepairReportRepairStatusEnum;
import com.eastfair.home.exceptioncode.HomeExceptionCode;
import com.eastfair.home.service.BuilderRepairReportService;
import com.eastfair.home.service.HomeRepairReportService;
import com.eastfair.home.service.HomeServiceProviderSpaceService;
import com.eastfair.home.vo.BuilderRepairReportVO;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.entity.CreatCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 搭建商报修申请
 * </p>
 *
 * @author dqq
 * @date 2022-11-24
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class BuilderRepairReportServiceImpl extends SuperServiceImpl<BuilderRepairReportMapper, BuilderRepairReport> implements BuilderRepairReportService {

    private static final String REPAIR_REPORT_NUMBER_FIELD = "repair_report_number";

    private static final int REPAIR_REPORT_NUMBER_LENGTH = 5;

    @Resource
    private HomeRepairReportService homeRepairReportService;

    @Resource
    private HomeServiceProviderSpaceService homeServiceProviderSpaceService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<BuilderRepairReport> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(BuilderRepairReport model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (model.getRepairStatus() == null) {
            model.setRepairStatus(BuilderRepairReportRepairStatusEnum.HAS_REPORT);
        }
        if (model.getReportTime() == null) {
            model.setReportTime(LocalDateTime.now());
        }
        if (model.getIsBookService() == null) {
            model.setIsBookService(0);
        }
        return R.successDef();
    }

    @Override
    public Page<BuilderRepairReportVO> listBuilderRepairReportVO(PageParams<BuilderRepairReportDTO> pageParams) {
        log.info("listRepairReportVO - 查询报修申请列表VO, pageParams={}", pageParams);
        BuilderRepairReportDTO model = pageParams.getModel();
        if (model.getHomeId() != null && model.getExhibitionManageId() != null) {
            // 查询主场在展会中负责的展厅
            List<String> spaceCodeList = homeServiceProviderSpaceService.listSpaceCodesByServiceProviderId(model.getHomeId(), model.getExhibitionManageId());
            model.setSpaceCodeList(spaceCodeList);
        }
        Page<BuilderRepairReport> pageParam = pageParams.buildPage();
        QueryWrapper<BuilderRepairReport> queryWrapper = createRepairReportQueryWrapper(pageParams.getModel());
        Page<BuilderRepairReport> page = page(pageParam, queryWrapper);
        Page<BuilderRepairReportVO> voPage = new Page<>();
        BeanUtil.copyProperties(page, voPage);
        List<BuilderRepairReport> list = page.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        List<BuilderRepairReportVO> voList = list
                .stream()
                .map(builderRepairReport -> BeanUtil.toBean(builderRepairReport, BuilderRepairReportVO.class))
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public List<BuilderRepairReportVO> listBuilderRepairReportVO(BuilderRepairReportDTO query) {
        log.info("listBuilderRepairReportVO - 查询搭建商报修申请列表, query={}", query);
        List<BuilderRepairReport> list = listBuilderRepairReport(query);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(builderRepairReport -> BeanUtil.toBean(builderRepairReport, BuilderRepairReportVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<BuilderRepairReport> listBuilderRepairReport(BuilderRepairReportDTO query) {
        QueryWrapper<BuilderRepairReport> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(BuilderRepairReport::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(StrUtil.isNotBlank(query.getRepairReportNumber()), BuilderRepairReport::getRepairReportNumber, query.getRepairReportNumber())
                .eq(query.getExhibitionManageId() != null, BuilderRepairReport::getExhibitionManageId, query.getExhibitionManageId())
                .eq(query.getCompanyId() != null, BuilderRepairReport::getCompanyId, query.getCompanyId())
                .eq(StrUtil.isNotBlank(query.getSpaceCode()), BuilderRepairReport::getSpaceCode, query.getSpaceCode())
                .eq(StrUtil.isNotBlank(query.getSiteName()), BuilderRepairReport::getSiteName, query.getSiteName())
        ;
        return list(queryWrapper);
    }

    @Override
    public BuilderRepairReport getByReportRepairNumber(String repairReportNumber) {
        BuilderRepairReportDTO builderRepairReportDTO = new BuilderRepairReportDTO();
        builderRepairReportDTO.setRepairReportNumber(repairReportNumber);
        List<BuilderRepairReport> list = listBuilderRepairReport(builderRepairReportDTO);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public BuilderRepairReportVO getVOByReportRepairNumber(String repairReportNumber) {
        log.info("getVOByReportRepairNumber - 报修单号获取报修申请VO, repairReportNumber={}", repairReportNumber);
        BuilderRepairReport repairReport = getByReportRepairNumber(repairReportNumber);
        if (repairReport == null) {
            return null;
        }
        return BeanUtil.toBean(repairReport, BuilderRepairReportVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BuilderRepairReport saveBuilderRepairReport(BuilderRepairReportDTO builderRepairReportDTO) {
        log.info("saveBuilderRepairReport - 保存搭建商报修申请, repairReportDTO={}", builderRepairReportDTO);
        // 生成报修单号
        if (StrUtil.isBlank(builderRepairReportDTO.getRepairReportNumber())) {
            String prefix = LocalDateTimeUtil.format(LocalDate.now(), "yyyyMMdd");
            String repairReportNumber = CreatCode.creatCode(baseMapper, REPAIR_REPORT_NUMBER_FIELD, REPAIR_REPORT_NUMBER_LENGTH, prefix);
            builderRepairReportDTO.setRepairReportNumber(repairReportNumber);
        }
        // 保存报修申请
        BuilderRepairReport repairReport = BeanUtil.toBean(builderRepairReportDTO, BuilderRepairReport.class);
        save(repairReport);
        return repairReport;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BuilderRepairReport updateBuilderRepairReport(BuilderRepairReportDTO builderRepairReportDTO) {
        log.info("updateBuilderRepairReport - 更新搭建商报修申请, repairReportDTO={}", builderRepairReportDTO);
        BuilderRepairReport repairReport = BeanUtil.toBean(builderRepairReportDTO, BuilderRepairReport.class);
        updateById(repairReport);
        return repairReport;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelBuilderRepairReport(String repairReportNumber) {
        log.info("cancelBuilderRepairReport - 取消搭建商报馆申请, repairReportNumber={}", repairReportNumber);
        BuilderRepairReport builderRepairReport = getByReportRepairNumber(repairReportNumber);
        if (builderRepairReport == null) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_NOT_EXIST);
        }
        if (BuilderRepairReportRepairStatusEnum.HAS_CHECK.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CANCEL.getCode(), "取消报修申请失败, 报修申请已检测");
        }
        if (BuilderRepairReportRepairStatusEnum.HAS_REPORT_VENUE.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CANCEL.getCode(), "取消报修申请失败, 报修申请已报馆");
        }
        if (builderRepairReport.getIsBookService() == BusinessConstant.YES) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CANCEL.getCode(), "取消报修申请失败，报修已预定服务");
        }
        if (BuilderRepairReportRepairStatusEnum.COMPLETE.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CANCEL.getCode(), "取消报修申请失败, 报修申请已完成");
        }
        builderRepairReport.setRepairStatus(BuilderRepairReportRepairStatusEnum.CANCEL);
        return updateById(builderRepairReport);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCheckResult(BuilderRepairReportDTO builderRepairReportDTO) {
        log.info("updateCheckResult - 更新搭建商维修申请检测结果, repairReportDTO={}", builderRepairReportDTO);
        BuilderRepairReport builderRepairReport = getByReportRepairNumber(builderRepairReportDTO.getRepairReportNumber());
        if (builderRepairReport == null) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_NOT_EXIST);
        }
        if (BuilderRepairReportRepairStatusEnum.HAS_REPORT_VENUE.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CHECK.getCode(), "报修检测失败, 报修申请已报馆");
        }
        if (BuilderRepairReportRepairStatusEnum.COMPLETE.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CHECK.getCode(), "报修检测失败, 报修申请已完成");
        }
        if (BuilderRepairReportRepairStatusEnum.CANCEL.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_CHECK.getCode(), "报修检测失败, 报修申请已取消");
        }
        builderRepairReport.setCheckResult(builderRepairReportDTO.getCheckResult());
        builderRepairReport.setRepairOpinion(builderRepairReportDTO.getRepairOpinion());
        builderRepairReport.setIsNeedCompensate(builderRepairReportDTO.getIsNeedCompensate());
        builderRepairReport.setRepairStatus(BuilderRepairReportRepairStatusEnum.HAS_CHECK);
        return updateById(builderRepairReport);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateReportVenue(String repairReportNumber) {
        log.info("updateReportVenue - 更新报修申请为已报馆, repairReportNumber={}", repairReportNumber);
        BuilderRepairReport builderRepairReport = getByReportRepairNumber(repairReportNumber);
        if (builderRepairReport == null) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_NOT_EXIST);
        }
        if (!MenuAffiliationEnum.P_COMPOSITE_VENUE.getCode().equals(builderRepairReport.getServiceProvideSystem())
                && !MenuAffiliationEnum.P_COMPOSITE_MATING.getCode().equals(builderRepairReport.getServiceProvideSystem())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_REPORT_VENUE.getCode(), "报修申请报馆失败, 服务不是场馆或配套商提供");
        }
        if (BuilderRepairReportRepairStatusEnum.HAS_REPORT_VENUE.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_REPORT_VENUE.getCode(), "报修申请报馆失败, 报修申请已报馆");
        }
        if (BuilderRepairReportRepairStatusEnum.COMPLETE.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_REPORT_VENUE.getCode(), "报修申请报馆失败, 报修申请已完成");
        }
        if (BuilderRepairReportRepairStatusEnum.CANCEL.eq(builderRepairReport.getRepairStatus())) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_CAN_NOT_REPORT_VENUE.getCode(), "报修申请报馆失败, 报修申请已取消");
        }
        // 更新搭建商报修申请为已报馆
        builderRepairReport.setRepairStatus(BuilderRepairReportRepairStatusEnum.HAS_REPORT_VENUE);
        updateById(builderRepairReport);
        // 保存综合服务报修申请
        homeRepairReportService.saveRepairReportByBuilder(builderRepairReport);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateComplete(BuilderRepairReportDTO builderRepairReportDTO) {
        log.info("updateComplete - 更新报修申请为已完成, repairReportDTO={}", builderRepairReportDTO);
        BuilderRepairReport builderRepairReport = getByReportRepairNumber(builderRepairReportDTO.getRepairReportNumber());
        if (builderRepairReport == null) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_NOT_EXIST);
        }
        builderRepairReport.setRepairStatus(BuilderRepairReportRepairStatusEnum.COMPLETE);
        builderRepairReport.setCompleteRemark(builderRepairReportDTO.getCompleteRemark());
        return updateById(builderRepairReport);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateIsBookService(BuilderRepairReportDTO builderRepairReportDTO) {
        log.info("updateIsBookService - 更新是否搭建商报修申请是否预定了服务, builderRepairReportDTO={}", builderRepairReportDTO);
        BuilderRepairReport builderRepairReport = getByReportRepairNumber(builderRepairReportDTO.getRepairReportNumber());
        if (builderRepairReport == null) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_NOT_EXIST);
        }
        builderRepairReport.setIsBookService(builderRepairReportDTO.getIsBookService());
        return updateById(builderRepairReport);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCompensateVenueAmount(BuilderRepairReportDTO builderRepairReportDTO) {
        log.info("updateCompensateVenueAmount - 更新需赔付场馆金额, builderRepairReportDTO={}", builderRepairReportDTO);
        BuilderRepairReport builderRepairReport = getByReportRepairNumber(builderRepairReportDTO.getRepairReportNumber());
        if (builderRepairReport == null) {
            throw BizException.wrap(HomeExceptionCode.REPAIR_REPORT_NOT_EXIST);
        }
        builderRepairReport.setCompensateVenueAmount(builderRepairReportDTO.getCompensateVenueAmount());
        return updateById(builderRepairReport);
    }

    /**
     * 生成RepairReport的查询参数.
     *
     * @param model the model
     * @return the query wrapper
     */
    private QueryWrapper<BuilderRepairReport> createRepairReportQueryWrapper(BuilderRepairReportDTO model) {
        QueryWrapper<BuilderRepairReport> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(BuilderRepairReport::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(model.getExhibitionManageId() != null, BuilderRepairReport::getExhibitionManageId, model.getExhibitionManageId())
                .eq(model.getCompanyId() != null, BuilderRepairReport::getCompanyId, model.getCompanyId())
                .eq(StrUtil.isNotBlank(model.getCompanyCode()), BuilderRepairReport::getCompanyCode, model.getCompanyCode())
                .like(StrUtil.isNotBlank(model.getCompanyName()), BuilderRepairReport::getCompanyName, model.getCompanyName())
                .like(StrUtil.isNotBlank(model.getRepairReportNumber()), BuilderRepairReport::getRepairReportNumber, model.getRepairReportNumber())
                .like(StrUtil.isNotBlank(model.getOrderNumber()), BuilderRepairReport::getOrderNumber, model.getOrderNumber())
                .like(StrUtil.isNotBlank(model.getSpaceName()), BuilderRepairReport::getSpaceName, model.getSpaceName())
                .like(StrUtil.isNotBlank(model.getSiteName()), BuilderRepairReport::getSiteName, model.getSiteName())
                .eq(model.getRepairStatus() != null, BuilderRepairReport::getRepairStatus, model.getRepairStatus())
                .eq(model.getServiceCategoryId() != null, BuilderRepairReport::getServiceCategoryId, model.getServiceCategoryId())
                .in(model.getSpaceCodeList() != null && !model.getSpaceCodeList().isEmpty(),
                        BuilderRepairReport::getSpaceCode, model.getSpaceCodeList())
                // 已取消的不展示
                .ne(BuilderRepairReport::getRepairStatus, BuilderRepairReportRepairStatusEnum.CANCEL)
        ;
        return queryWrapper;
    }
}
